package com.wjw.java.model;

/**
 * 单例模式：成员运行时,该类有且只有一个实例对象
 * ---------------------------------------------------------------
 * 实现步骤：
 * 1.构造器私有化,防止直接new
 * 2.类的内部直接创建一个该类的private static对象
 * 3.向外暴露一个public的getInstance()方法,实例化对象
 *
 * ---------------------------------------------------------------
 * 饿汉式:类被加载的时候,就已经实例化对象了
 * 1.构造器私有化private,防止直接new
 * 2.类的内部直接创建一个该类的private static对象,并实例化该对象
 * 3.向外暴露一个public static的getInstance()方法,并返回对象实例
 * 4.Runtime类就是一个经典的饿汉式单例
 *
 * 懒汉式:用到该类的getInstance(),才会返回对象,下一次调用getInstance(),返回的是上一次的对象
 * 1.构造器私有化private,防止直接new
 * 2.类的内部直接创建一个该类的private static对象,不实例化
 * 3.向外暴露一个public static的getInstance()方法,并返回对象实例
 * ---------------------------------------------------------------
 * 饿汉式和懒汉式的区别：
 * 1.饿汉式是在类加载的时候就创建了对象实例;懒汉式是在调用getInstance()方法时才创建对象实例
 * 2.饿汉式是线程安全的;懒汉式是线程不安全的
 * 3.饿汉式浪费资源,懒汉式节约资源
 */
public class SingletonModel {

    public static void main(String[] args) {
        //GirlFriend gf1 = new GirlFriend("AA");
        //GirlFriend gf1 = new GirlFriend("BB");

        //饿汉式
        Hungry h1 = Hungry.getInstance();
        System.out.println(h1);
        Hungry h2 = Hungry.getInstance();
        System.out.println(h2);
        System.out.println(h1 == h2);//true

        //懒汉式
        Lazy l1 = Lazy.getInstance();
        System.out.println(l1);
        Lazy l2 = Lazy.getInstance();
        System.out.println(l2);
        System.out.println(l1 == l2);//true
    }
}

//饿汉式
class Hungry{
    /**
     * 饿汉式的问题：直接调用System.out.println(Hungry.num);
     * 也会执行构造器中的代码,如果代码太多,就浪费资源
     */
    public static int num1 = 100;

    private String name;

    //1.构造器私有化,防止直接new
    private Hungry(String name) {
        //System.out.println("饿汉式：构造器被调用了！！！");
        this.name = name;
    }

    //2.类的内部直接创建一个该类的private static对象,并实例化该对象
    private static Hungry gf = new Hungry("饿汉模式");

    //3.向外暴露一个public static的getInstance()方法,并返回对象实例
    public static Hungry getInstance(){
        return gf;
    }

    @Override
    public String toString() {
        return "Hungry{" +
                "name='" + name + '\'' +
                '}';
    }
}

//懒汉式
class Lazy{
    /**
     * 懒汉式：直接调用System.out.println(Lazy.num2);
     * 不会执行构造器中的代码,只有在实例化的时候才会执行构造器中的代码
     */
    public static int num2 = 200;

    private String name;

    //1.构造器私有化,防止直接new
    private Lazy(String name){
        //System.out.println("懒汉式：构造器被调用了！！！");
        this.name = name;
    }
    //2.类的内部直接创建一个该类的private static对象,不实例化
    private static Lazy lazy;

    //3.向外暴露一个public static的getInstance()方法,并返回对象实例
    public static Lazy getInstance(){
        if(lazy == null){
            lazy = new Lazy("懒汉模式");
        }
        return lazy;
    }

    @Override
    public String toString() {
        return "Lazy{" +
                "name='" + name + '\'' +
                '}';
    }
}